import com.sun.org.apache.xalan.internal.xsltc.compiler.Output;
import dataflowVariety.Term;


package codegen
{	
	class CodeGenenrator(root : SyntaxNode, path : String = "")
	{
	  // the syntax tree
	  protected var tree = new SyntaxTree(root)
	  	  
	  // widget counter
	  private var count : Int = 0;
	  protected def getCount : Int = 
	  { 
	    count += 1; 
	    count;
	  }
	  
	  // generates the output file (called after the parsing stage is done).
	  def GenerateCode()
	  {	    
	    // open a file using the path to the output *.scala file
	    val out_file = new java.io.FileOutputStream(path) 
	    val out_stream = new java.io.PrintStream(out_file); 
	  	    
	    // print header (imports and such)
	    out_stream.print(getHeader())
	    
	    // write the whole tree into a file
	    out_stream.print(tree.getCommands())
	    	    
	    // end the file
	    out_stream.print(getFooter());
	   
	    out_stream.close();    
	    out_file.close();
	  }
	        
	  protected def getHeader() : String = 
	  {
	    var header = "import layoutVariety._;\r\nimport dataflowVariety._;\r\n\r\nobject program\r\n{\r\n\t" +
	    			 "private val wf = WidgetFactory;\r\n\t" + 
	    			 "private val af = AttributeFactory;\r\n\t" + 
	    			 "val mainWindow = new MainWindow();\r\n\t" + 
	    			 "mainWindow.maximize();\r\n\t";
	    			 	
	    header;
	  }
	  protected def getFooter() : String = 
	  {
	    var footer = "mainWindow.setMainBox(mainBox);\r\n}\r\n";
	      
	    footer;
	  }
	  
	
	  /**
	   * Boxes and widgets generation 
	   */
	  
	  // called when a box definition is parsed
	  def createBox(name : String): SmartSyntaxNode = 
	  {
	    var n = name
	      
	    if (name == "main_window")
	    { 
	      n = "mainBox"; 
        }
    
	    var cmd = (node:SyntaxNode) => "private var " + n + " = wf.getWidget(\"box\").asInstanceOf[Box];\r\n\t" +
	    							"mainWindow.addWidget(\""+n+"\","+n+");\r\n\t";
	    
	    var node = new SmartSyntaxNode();
	    node.setCommandFunction(cmd);
	    node.name = n;
	    
	    node;
	  }
	  
	  // called when an anonymus box is cerated
	  def createBox() : SmartSyntaxNode = 
	  {
	    // generate a unique name for the widget
	    val name : String = "box_"+getCount;
	    
	    var cmd = (n:SyntaxNode) => "private var " + name + " = wf.getWidget(\"box\").asInstanceOf[Box];\r\n\t" +
	    							"mainWindow.addWidget(\""+name+"\","+name+");\r\n\t";
	    
	    var node = new SmartSyntaxNode();
	    node.setCommandFunction(cmd);
	    node.name = name;
	    
	    node;
	  }
	  
	  // called when over constraining is discovered
	  def convertToOverConstrainedBox(scrollDirection : String, node : SmartSyntaxNode) : Unit =  
	  {
	    var cmd = (n:SyntaxNode) => "private var " + node.name + " = wf.getWidget(\"overBox\");\r\n\t" + 
	    						    node.name + "." + "setScrollDirection(ScrollDirection."+scrollDirection+");\r\n\t";
	    
	    node.setCommandFunction(cmd);
	  }
	 
	  // called when under constraining is discovered
	  def convertToUnderConstrainedBox(splitDirection : String, node : SmartSyntaxNode) : Unit =  
	  {
	    var cmd = (n:SyntaxNode) => "private var " + node.name + " = wf.getWidget(\"underBox\");\r\n\t" + 
						    		node.name + "." + "setSplitDirection(AlignDirection."+splitDirection+");\r\n\t";

    	node.setCommandFunction(cmd);
	  }
	  
	  // called when a widget definition is parsed
	  def addWidgetToBox(widgetType : String): SyntaxNode =  
	  {
	    // generate a unique name for the widget
	    val name : String = widgetType+"_"+getCount;
	    
	    /*code generation*/
			   				  		 	
	    var cmd = (n:SyntaxNode) =>  "private var " + name + " = wf.getWidget(\""+widgetType+"\");\r\n\t" +     // create the widget
						   			 n.getParentName() + "." + "addWidget("+ name +");\r\n\t"  +  				// add to the parent
	    							 "mainWindow.addWidget(\""+name+"\","+name+");\r\n\t";	 					// add to main window
	    							 
	    
	    /*syntax node creation*/
	    var node = new SyntaxNode();
	    node.name = name;
	    node.setCommandFunction(cmd);
	    
	    return node;
	  }

	  // called when a box is added to another box
	  def addBoxToBox(name : String) : SyntaxNode = 
	  {
	    // add box to its parent
	    var cmd = (n:SyntaxNode) => n.getParentName() + "." + "addWidget("+ name +");\r\n\t";  	
	    	    
	    var node = new SyntaxNode();
	    node.isBoxAddition = true;
	    return node;
	  }
	  
	  // called when a box alignment needs to be set
	  def setAlignment(alignment : String) : SyntaxNode = 
	  {
		var cmd = (n : SyntaxNode) => n.getParentName() + "." + "setAlignment(AlignDirection."+ alignment +");\r\n\t";
	    
		var node = new SyntaxNode();
	    node.setCommandFunction(cmd);
	    return node;
	  }

	  
	  /**
	   * Attribute and size generation  
	   */	  

  	  // called when a virtual custom attribute attribute is parsed
	  def setVirtualAttribute(term : Term,realAttName : String, isBidi : Boolean) : SyntaxNode = 
	  {
	     var cmd = (n : SyntaxNode) => n.getParentName() + "." + "setCustomAttribute(\""+ realAttName +"\",af.getVirtualFromTerm("+term.toString()+"),"+isBidi.toString()+");\r\n\t";
 		 var node = new SyntaxNode();
	     node.setCommandFunction(cmd);
	     return node;
	  }
	  
	  // called when an attribute is set to a real value
	  def setRealAttribute(realAttName : String, value : String): SyntaxNode =  
	  {
	    var cmd = (n : SyntaxNode) => n.getParentName() + "." + "setAttByName(\""+ realAttName +"\","+value+");\r\n\t";
	    
		var node = new SyntaxNode();
	    node.setCommandFunction(cmd);
	    return node;
	  }
	  
	  def addCustomAttribute(realAttName: String, custAttName: String, isBidi : Boolean) : SyntaxNode = 
	  {
	    var cmd = (n : SyntaxNode) => n.getParentName() + "." + "setCustomAttribute(\""+ realAttName +"\",af.getCutomAttByName(\""+ custAttName +"\"),"+isBidi.toString()+");\r\n\t";
	    
		var node = new SyntaxNode();
	    node.setCommandFunction(cmd);
	    return node;
	  }	
	  
	  // called when an assignment to a custom attribute it parsed
	  def assignToCustomAttribute(name : String, value : Double) : SyntaxNode = 
	  { 
	     var cmd = (n : SyntaxNode) => "af.assign(\""+name+"\",\""+value+"\");\r\n\t"
 		 var node = new SyntaxNode();
	     node.setCommandFunction(cmd);
	     return node;
	  }
	  
	  // called when a simple equation is parsed
	  def addEquation(term : Term) : SyntaxNode = 
	  {
	     var cmd = (n : SyntaxNode) => "af.loadDataFromTerm("+term.toString+");\r\n\t"
 		 var node = new SyntaxNode();
	     node.setCommandFunction(cmd);
	     return node;
	  }  
	}  
}